package top.wilsonlv.jaguar.cloud.websocket.sdk.pusher;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
import top.wilsonlv.jaguar.cloud.websocket.sdk.WebsocketConstant;
import top.wilsonlv.jaguar.cloud.websocket.sdk.dto.MessagePushTopic;
import top.wilsonlv.jaguar.cloud.websocket.sdk.dto.WebsocketConnection;
import top.wilsonlv.jaguar.cloud.websocket.sdk.dto.WebsocketMessage;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * @author lvws
 * @since 2021/5/6
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class WebsocketPusher {

    private final RedisTemplate<String, Serializable> redisTemplate;

    private final JmsTemplate jmsTopicTemplate;

    public boolean push2User(Long userId, WebsocketMessage message) {
        return this.push2User(userId, null, message);
    }

    public boolean push2User(Long userId, String accessToken, WebsocketMessage message) {
        String onlineKey = String.format(WebsocketConstant.ONLINE_KEY_FORMAT, userId);
        BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(onlineKey);
        Map<Object, Object> entries = operations.entries();
        if (entries == null) {
            return false;
        }

        boolean online = false;
        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
            WebsocketConnection websocketConnection = (WebsocketConnection) entry.getValue();
            if (websocketConnection.getExpireTime().isBefore(LocalDateTime.now())) {
                operations.delete(websocketConnection.getSessionId());
                continue;
            }

            if (accessToken != null && !websocketConnection.getAccessToken().equals(accessToken)) {
                continue;
            }

            MessagePushTopic topic = new MessagePushTopic();
            topic.setUserId(userId);
            topic.setSessionId(websocketConnection.getSessionId());
            topic.setServerInstanceId(websocketConnection.getServerInstanceId());
            topic.setMessage(message);

            jmsTopicTemplate.send(WebsocketConstant.DESTINATION_WEBSOCKET_PUSH2USER, session ->
                    session.createObjectMessage(topic));

            online = true;
        }
        return online;
    }

    public void push2Session(String sessionId, WebsocketMessage message) {
        MessagePushTopic topic = new MessagePushTopic();
        topic.setSessionId(sessionId);
        topic.setMessage(message);

        jmsTopicTemplate.send(WebsocketConstant.DESTINATION_WEBSOCKET_PUSH2SESSION, session ->
                session.createObjectMessage(topic));
    }

}